/* Copyright (c) 2006 celumsolutions. All Rights Reserved. */
package com.swingolf.service;

import com.swingolf.model.Level;
import com.swingolf.model.Player;
import com.swingolf.model.Rank;
import com.swingolf.model.Tournament;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.*;

/**
 * @author rtm
 * @since 15.09.11
 */
@Repository
public class RankService {

  @Autowired
  PlayerService playerService;

  public Collection<Rank> getRanks(Level level) {
    return getRanks(level, null);
  }

  public Collection<Rank> getRanks(Level level, Tournament tournament) {
    return getRanks(playerService.findPlayers(), level, tournament);
  }

  public Collection<Rank> getRanks(List<Player> players, Level level, Tournament tournament) {
    Map<Integer, Set<Player>> ranking = new TreeMap<Integer, Set<Player>>();
    for (Player player : players) {
      Integer score = player.getScore();
      if (!ranking.containsKey(score)) {
        ranking.put(score, new HashSet<Player>());
      }
      Set<Player> rankedPlayers = ranking.get(score);
      rankedPlayers.add(player);
    }
    LinkedList<Rank> result = new LinkedList<Rank>();
    int i = 1;
    for (Map.Entry<Integer, Set<Player>> entry : ranking.entrySet()) {
      int j = 0;
      for (Player player : entry.getValue()) {
        if (!player.getScore().equals(0) && match(level, player) && match(tournament, player)) {
          result.add(new Rank(i, player));
          j++;
        }
      }
      i += j;
    }
    return result.subList(0, result.size()<5 ? result.size() : 5);
  }

  private boolean match(Tournament tournament, Player player) {
    return tournament == null ? true : tournament.equals(player.getTournament());
  }

  private boolean match(Level level, Player player) {
    return level == null ? true : level.equals(player.getLevel());
  }

  public Rank getFirstRank(Tournament scramble) {
    return getRanks(scramble).isEmpty() ? null : getRanks(scramble).iterator().next();
  }

  public Collection<Rank> getRanks() {
    return getRanks((Level) null);
  }

  public Collection<Rank> getRanks(Tournament tournament) {
    return getRanks(null, tournament);
  }
}
